home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Games Collection 1
/
software vault.zip
/
software vault
/
CDR10
/
YICN23.ZIP
/
DOC
/
YICONS.DOC
< prev
next >
Wrap
Text File
|
1993-03-06
|
34KB
|
941 lines
Documentation file for YakIcons version 2.0
----------------------------------------------------------------------
YakIcons is a free shareware graphics library encompassing many aspects
of game design and mechanics. It is a series of object-oriented modules
for Borland C++ version 3.1 and covers mouse and joystick support, sampled
sound, fast icon drawing, restorable screen areas, editable fonts, tiled
maps, etc, etc.
All units are compiled in the large memory model; I have no idea what will
happen if you use others.
Thanks and other dedications:
J. Slagel-- his xblt code was my first inspiration.
Themie Gouthas-- his xlib04 library is the core of the yakIcons system. Mr.
Gouthas has been invaluable in the development of yakIcons, if only
because his library started the whole thing rolling.
Christopher Christensen-- his post on rec.games.programmer became the
core routines for yakStick, the joystick module.
Chris Busch -- wrote the original bits of the collision code.
SBF-- the Soundblaster Freedom Project, whose routines form the center of
the yakSample and yakVoc classes.
Jo E. Carter Putz-- my lovely wife, who showed a great deal of patience
during the development of yakIcons and will no doubt be called upon
do do more of the same in the future.
Roslyn-- my dog, a seven-month-old Klee Kai, with whom I should have spent a
lot more time playing!
and, of course, you-- any programmer who takes the time to try and write a
game.
On with the docs!
*
Any game, no matter how simple, requires graphics in this day and age. The
most cerebral and atmospheric games to me are still text adventures-- but
writing one is relatively unrewarding, since the user base is quite small.
Graphics, though, opens up a great can of worms for the amateur programmer.
The most immediate problem the programmer has is this: how to place a known
graphic onto the screen?
--------------------------------------------------------------------------
THE ICON CLASS
The icon class is truly the heart of the yakIcons library. It provides
a fast, easy solution to the "get this graphic onto that screen at those
coordinates" problem. Here's the header file, and we'll go through it by
parts.
#ifndef ICON.H
#define ICON.H
#include "stddefs.h"
#include "yaklib.h"
class icon
{
public:
enum flagType {normal = 0, fast = 1};
int width, height;
flagType flags;
char * unrolledPic;
icon() {width = height = byteWidth = 0; flags = normal; unrolledPic = NULL; collisionMap = NULL;};
~icon() {delete unrolledPic; delete collisionMap;};
inline byte getPixel(int x, int y);
void save(char * filename);
char * useData(unsigned char * myPointer, flagType iflags = normal);
char * load(char * filename, flagType iflags = normal, yakLib * myYakLib = NULL);
inline void show(int x, int y, word offset);
inline void hide(int x, int y, word to_offset, word from_offset);
inline void showMasked(int x, int y, word offset);
//collision system code parts inserted here. All icons will have collision
//maps.
byte * collisionMap; //contains collision points
int byteWidth; //width in bytes.
int setWPacked(int, int); //allocates space for array
int setCollisionBit(int ix, int iy, booleanFlags flag = on);
int getCollisionBit(int ix, int iy);
void spewCollisionTable(void);
int makeCollisionMap(void);
int hitXY(int myX, int myY, icon* target, int targetX, int targetY);
// icon zooming code parts inserted here. Only one zoomtable will exist for
// all icons.
static byte ** zoomTable;
static int zoomTableWidth;
static byte ** setZoomTable(int newWidth);
static void spewZoomTable(void);
icon * zoomedIcon(int newWidth);
void showZoomed(int x, int y, word offset, int newWidth);
};
char * unRollBlt(char * rolledBlt, int &iwidth, int &iheight);
char * rollBlt(char * unRolledBlt, int &iwidth, int &iheight);
#endif
Now by parts:
enum flagType {normal = 0, fast = 1};
This is a type which is enumerated for accuracy (rather than #DEFINEing the
values). Normal is a normal bitmap; fast is a compiled bitmap (up to four
times faster).
int width, height;
width and height of the image, in pixels.
flagType flags;
the variable used to hold the flagtype above.
char * unrolledPic;
the actual image data is stored here. See formats.doc.
icon() {width = height = 0; flags = normal; unrolledPic = NULL;};
default constructor.
~icon() {delete unrolledPic; delete collisionMap;};
default destructor (frees up memory used by the bitmap and collision map).
byte getPixel(int x, int y);
returns the color of a given pixel in the bitmap. Used in gadgets.cpp, and
I'm sure has other uses as well! Sorry, no putPixel yet (didn't see the need)
void save(char * filename);
saves an icon to disk under the given filename. This should end in .yak
for compatibility with animicon, etc.
char * useData(unsigned char * myPointer, flagType iflags = normal);
uses data in a header file as definition data for an icon. Make a header
file out of an icon with bin2hdr, then use the pointer as an argument for
useData.
char * load(char * filename, flagType iflags = normal, yakLib * myYakLib = NULL);
loads an icon from disk. Flags can be set to determine if the icon is fast
or normal. Fast icons can't be saved correctly or getPixel'd! myYakLib is
the address of a yakLib to load from.
inline void show(int x, int y, word offset);
puts the bitmap to screen, including color zero. Compiled bitmaps are auto-
matically masked.
inline void hide(int x, int y, word to_offset, word from_offset);
copies a square from from_offset to to_offset, "hiding" the icon's position.
inline void showMasked(int x, int y, word offset);
puts the bitmap to screen, excluding color zero (which is transparent).
byte * collisionMap; //contains collision points
contains the one-bit-per-pixel collision map for the icon.
int byteWidth; //width in bytes.
int setWPacked(int, int); //allocates space for array
sets up the collision map.
int setCollisionBit(int ix, int iy, booleanFlags flag = on);
sets a bit in the collision map.
int getCollisionBit(int ix, int iy);
returns the value of a bit in the collision map.
void spewCollisionTable(void);
"spews" the collision map of an icon to the current output device. Used
for debugging only.
int makeCollisionMap(void);
References the bitmap of an icon and creates a collision map from it.
int hitXY(int myX, int myY, icon* target, int targetX, int targetY);
Checks to see if the object collided with the icon "target".
static byte ** zoomTable;
The zoomTable contains data for zooming icons. If a pixel is to be drawn
at a new size, the zoomTable will contain a "1"; if not, a "0".
static int zoomTableWidth;
The width of the zoomTable.
static byte ** setZoomTable(int newWidth);
Creates the indices for the zoom table based on the width of zoomable icons.
static void spewZoomTable(void);
Spews the zoom table to the output device. Used for debugging.
icon * zoomedIcon(int newWidth);
Allocates space for and returns a new icon, zoomed to the new width
"newWidth".
void showZoomed(int x, int y, word offset, int newWidth);
Shows an icon at a position, zoomed to a new width.
char * unRollBlt(char * rolledBlt, int &iwidth, int &iheight);
char * rollBlt(char * unRolledBlt, int &iwidth, int &iheight);
these two functions aren't part of the icon class, but they do make
things a little easier when converting from a linear to a planar bitmap
(unRollBlt) or a planar to linear (rollBlt). If the linear bitmap isn't
a multiple of 4 wide, unRollBlt pads it with zeros. Look at these functions
before you use them; they're a little confusing to me still.
Got all that? The basic ideas are pretty straightforward. Look at the
example programs, particularly view.cpp and vitals.cpp.
Once the programmer can put objects onto the screen, the next big step is
animation. This could be a hassle-- the programmer would have to store a
table of shapes in memory, figure out which one to draw at a given time,
and put it there. Or, they could just use a handy animicon!
------------------------------------------------------------------------
THE ANIMICON CLASS
The animicon is simply a linked list of icons. With each draw, it auto-
matically advances itself to the next frame; the programmer needs to do
nothing.
#ifndef ANIMICON.H
#define ANIMICON.H
#include <stddef.h>
#include "stddefs.h"
#include "icon.h"
class animiconNode
{
public:
animiconNode * nextFrame;
animiconNode * prevFrame;
icon picture;
animiconNode() {nextFrame = NULL; prevFrame = NULL;}
animiconNode(byte * iconData, animiconNode * nextIcon)
{picture.useData(iconData); nextFrame = nextIcon; prevFrame = NULL;};
};
class animicon
{
public:
animiconNode * firstFrame;
animiconNode * lastFrame;
animiconNode * thisFrame;
byte numberOfFrames;
animicon() {firstFrame = lastFrame = thisFrame = NULL; numberOfFrames = 0;}
animicon(char * filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
~animicon();
char far * add(animiconNode * thisNode);
char far * add(char far *filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
inline void show(int x, int y, word pagebase);//virt
inline void draw(int x, int y, word pagebase);//virt
inline void showZoomed(int x, int y, word offset, int newWidth);
inline void drawZoomed(int x, int y, word offset, int newWidth);
inline void advance(void); //virt
void removeTail(void);
void addAll(char * filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
void hide(int x, int y, word toOffset, word fromOffset);
};
class animslave
{
public:
animiconNode * thisFrame;
animslave() {thisFrame = NULL;}
virtual void advance(void);
virtual void advance(int numFrames);
inline void draw(int x, int y, word pagebase);//virt
inline void show(int x, int y, word pagebase);//virt
inline void showZoomed(int x, int y, word offset, int newWidth);
inline void drawZoomed(int x, int y, word offset, int newWidth);
};
#endif
You probably won't have to make any instances of an animiconNode, so we'll
go straight to animicon.
class animicon
{
public:
animiconNode * firstFrame; //the first frame
animiconNode * lastFrame; //the last frame
animiconNode * thisFrame; //the frame currently being shown
byte numberOfFrames; //number of frames in the series
animicon() {firstFrame = lastFrame = thisFrame = NULL; numberOfFrames = 0;}
basic constructor.
animicon(char * filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
This reads just like the icon::load function and does just that-- the only
difference is that it loads all the frames of the animation.
~animicon();
default destructor; frees up all frames of the animicon.
char far * add(animiconNode * thisNode);
adds an animiconNode as a frame in the animicon.
char far * add(char far *filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
adds a .yak file as a frame.
inline void show(int x, int y, word pagebase);//virt
inline void draw(int x, int y, word pagebase);//virt
inline void showZoomed(int x, int y, word offset, int newWidth);
inline void drawZoomed(int x, int y, word offset, int newWidth);
inline void advance(void); //virt
show shows the icon and advances it a frame. Draw draws the icon and does
not advance. Advance advances the icon one frame of animation. ShowZoomed
and drawZoomed are the same as show and draw, but also rescale the icon.
void removeTail(void);
removes the last frame of the animation.
void addAll(char * filename, icon::flagType flags = icon::normal, yakLib * myYakLib = NULL);
adds all icons in the animation as .yak files.
void hide(int x, int y, word toOffset, word fromOffset);
see the icon implementation.
};
As you might imagine, animicons are memory hogs, particularly if theyr'e
fast (compiled) icons. A nice solution to this problem if you have
many instances of a certain icon is the animslave class, which basically
points to an animicon:
-------------------------------------------------------------------------
THE ANIMSLAVE CLASS
class animslave
{
public:
animiconNode * thisFrame; //the frame currently pointed to
animslave() {thisFrame = NULL;} //the default constructor
virtual void advance(void);
advances the animslave one frame along the animicon
virtual void advance(int numFrames);
advances the animslave a given number of frames. Advancing an animslave
a random number of frames is a good way to get several similar objects out
of sync. Note that advancing an animslave does not affect other slaves of
the same animicon, nor does it affect the animicon itself!
inline void draw(int x, int y, word pagebase);//virt
inline void show(int x, int y, word pagebase);//virt
inline void showZoomed(int x, int y, word offset, int newWidth);
inline void drawZoomed(int x, int y, word offset, int newWidth);
you know this by now, I'm sure.
};
Obviously a good way to utilize these classes is to take a table of animicons
and make several instances of animslaves to point to them. You could
cover a screen this way with minimal memory usage! And that's just what
we'll do. No game is complete without a good background, and tiled back-
grounds of the ultima/wargame/nintendo style can be nice and effective.
--------------------------------------------------------------------------
THE ANIMAP CLASS
The animated map is a staple of the wargamer or adventure maker. We'll
make ours out of an array of map squares that know how to draw themselves:
#ifndef ANIMAP.H
#define ANIMAP.H
#include "stddefs.h"
#include "animicon.h"
class animactor;
class animapSquare : public animslave
{
public:
byte myIconNumber, myTerrainType;
int refresh; //should we refresh this square??
animactor * nextActor;
animapSquare() : animslave() {thisFrame = NULL; nextActor = NULL; myIconNumber = myTerrainType = 0;};
inline void display(int x, int y, word pageBase, int squareWidth);
virtual void advance(void);
void drawActors(int x, int y, word pageBase);
};
typedef char fileNameString[15];
class animap
{
public:
byte squareWidth;
word width, height;
word numIcons;
int lastScreenX, lastScreenY; //last pixel at which plotting started
int lastMapX, lastMapY; //last map square at which plotting started
int lastDrawWidth, lastDrawHeight; //width and height of last draw
animapSquare * * mapData;
animicon * iconTable;
fileNameString * iconNames;
animap(int numicons, int squidth, int iwidth, int iheight);
animap(char * filename, yakLib * myYakLib = NULL); //loads and constructs map!
~animap();
void * isInSquare(int x, int y, byte identity);
void draw(int centerx, int centery, int screenx, int screeny, int radx,int rady, word offset);
void show(int centerx, int centery, int screenx, int screeny, int radx,int rady, word offset);
void drawXY(int left, int top, int screenLeft, int screenTop, int width,int height, word offset);
void showXY(int left, int top, int screenLeft, int screenTop, int width,int height, word offset);
void smartRefresh(int deltaX, int deltaY, word offset);
void advance(void);
void loadIcon(int position, char * filename, yakLib * myYakLib = NULL);
void save(char * filename);
void load(char * filename);
void setSquare(word x, word y, byte icon_number);
void reset(void);
void randomize(void);
};
#endif
class animapSquare : public animslave
{
public:
byte myIconNumber, myTerrainType;
These are numbers meant for categorizing terrain. The icon number is the
number of the icon that will be drawn when this square is shown. The
terrain type is the type of terrain it really is (ie if you wanted to have
an invisible path through a swamp, set the icon to "swamp" and the terrain
type to "road".
int refresh; //should we refresh this square??
used by smartRefresh();
animactor * nextActor; //a pointer to the first actor on the square
animapSquare() : animslave() {thisFrame = NULL; nextActor = NULL; myIconNumber = myTerrainType = 0;};
default constructor.
inline void display(int x, int y, word pageBase, int squareWidth);
draws the map square and all the actors on it.
virtual void advance(void);
advances the map square one frame and all its actors one frame and one
script line.
void drawActors(int x, int y, word pageBase);
draws the actors on a map. For a laugh, call this without calling draw()
or display(); the actors will appear without any landscape around them.
Darkness maybe?
};
These squares are organized with the larger class, animap:
class animap
{
public:
byte squareWidth; //width of a map square in pixels
word width, height; //width and height of the map, in squares
word numIcons; //number of icons in the map
int lastScreenX, lastScreenY; //last pixel at which plotting started
int lastMapX, lastMapY; //last map square at which plotting started
int lastDrawWidth, lastDrawHeight; //width and height of last draw
animapSquare * * mapData; //ah, the actual map data!
animicon * iconTable; //table of animicons. Sound familiar?
fileNameString * iconNames; //names of the icons, for loading/saving.
animap(int numicons, int squidth, int iwidth, int iheight);
Okay, there's no default constructor for the animap. This will take the
arguments and dynamically allocate memory for a map of the given speci-
fications. No icons are loaded-- the map is NOT ready for use.
animap(char * filename, yakLib * myYakLib = NULL); //loads and constructs map!
This loads a map from a .map file on disk. If myYakLib is given, then
the map's icons are loaded from the given yakLib. The .map file is NOT
loaded from the yakLib! (didn't have time).
~animap();
default destructor. Frees up map data and icon data.
void * isInSquare(int x, int y, byte identity);
Queries a square to see if there is an actor with the given identity within.
void draw(int centerx, int centery, int screenx, int screeny, int radx,int rady, word offset);
draws the map, using the square centerx, centery as the center (!), screenx
and screeny for the center on the screen, radx and rady as the x and y
radii (radx=1, rady = 1 shows nine squares), and offset as the screen
offset to write to. Does not advance icons or actors.
void show(int centerx, int centery, int screenx, int screeny, int radx,int rady, word offset);
Same as above, but advances icons and actors.
void drawXY(int left, int top, int screenLeft, int screenTop, int width,int height, word offset);
void showXY(int left, int top, int screenLeft, int screenTop, int width,int height, word offset);
same as above, but works on top, left, and width instead of centerx, centery,
and radius.
void smartRefresh(int deltaX, int deltaY, word offset);
redraws the area of screen last drawn on, refreshing only those tiles that
require it. Actors and map squares larger than squareWidth may not be drawn
correctly. Very fast.
void advance(void);
advances icons and actors without drawing them.
void loadIcon(int position, char * filename, yakLib * myYakLib = NULL);
loads a yakIcon into a given position in the icon table.
void save(char * filename);
saves the map under the given filename.
void load(char * filename);
loads the map from the given filename.
void setSquare(word x, word y, byte icon_number);
sets a square to a given icon number. TerrainType = icon number!
void reset(void);
Hmm; I can't remember what this does. Ah! This resets every square's icon
to that square's icon number. Useful if icon pointers get hosed.
void randomize(void);
Randomizes every square on the map. Can be dangerous if all icons aren't
loaded in! I used it for debugging purposes; I doubt it could really be
useful in a game.
};
Okay, we're almost ready for the fun part. If the animap is the stage,
the actor class is naturally next. But before I tell you that story, I
have to tell you this one: actors work from a script, and before you
go for actors, take a peek at...
------------------------------------------------------------------------
THE SCRIPT CLASS
#ifndef SCRIPT.H
#define SCRIPT.H
#include <stddef.h>
#include "stddefs.h"
class scriptNode
{
public:
enum scriptCommand {doNothing, fineMoveRel, fineSlide, turn};
scriptNode * nextLine; // what it should do next.
byte command;
int mapX, mapY;
int squareX, squareY;
scriptNode() {nextLine = NULL; command = mapX = mapY = squareX = squareY = 0;};
scriptNode(byte icommand, int ix, int iy, int isquareX, int isquareY);
};
class script
{
public:
scriptNode * firstLine, * lastLine, * thisLine;
script() {firstLine = thisLine = lastLine = NULL;}
void addLine(byte command, int mapX, int mapY, int squareX, int squareY);
void addCommand(scriptNode::scriptCommand command, int mapX, int mapY, int squareX, int squareY);
void advanceLine(void);
};
#endif
A scriptNode is like a line in a script. It tells the actor what to do
NOW.
class scriptNode
{
public:
enum scriptCommand {doNothing, fineMoveRel, fineSlide, turn};
These are the four commands currently available:
doNothing: does nothing.
fineMoveRel: moves the actor (squareX, squareY) pixels
fineSlide: moves the actor (squareX, squareY) pixels in (mapX) turns
turn: turns a facing-actor (factor) a given direction (mapX)
scriptNode * nextLine; // what it should do next.
byte command;
the command in this line of script
int mapX, mapY;
two numbers used in the line
int squareX, squareY;
two more numbers used in the line (see scriptCommand above)
scriptNode() {nextLine = NULL; command = mapX = mapY = squareX = squareY = 0;};
default constructor
scriptNode(byte icommand, int ix, int iy, int isquareX, int isquareY);
constructor which sets all the appropriate variables.
};
Like an animicon is made up of animiconNodes, a script is made up of
scriptNodes:
class script
{
public:
scriptNode * firstLine, * lastLine, * thisLine; //look familiar?
script() {firstLine = thisLine = lastLine = NULL;}
default constructor
void addLine(byte command, int mapX, int mapY, int squareX, int squareY);
adds a new scriptNode to the script. Does no parsing.
void addCommand(scriptNode::scriptCommand command, int mapX, int mapY, int squareX, int squareY);
adds several scriptNodes to the script, depending on the command. Fineslide,
for example, adds several fineMoveRels
void advanceLine(void);
advances one line in the script, deleting the line just executed and freeing
its memory for future use.
};
--------------------------------------------------------------------------
THE ACTOR CLASS
#ifndef ACTOR.H
#define ACTOR.H
#include "animicon.h"
#include "animap.h"
#include "script.h"
#define MAX_ICONS 20
class event;
class animactor : public animslave, public script
{
public:
byte myIconNumber; // what do we look like?
byte myIdentity; // ...and what ARE we?
word mapX, mapY; //position on parent map
int lastMapX, lastMapY;
byte squareX, squareY; //position on map square, so we can move finely
animactor * nextActor;
animactor * spawningActor;
animactor * spawnedActor;
animap * mymap;
static animicon * actorIcons;
animactor() : animslave() {nextActor = spawnedActor = spawningActor = NULL; mymap = NULL; mapX = mapY = squareX = squareY = myIconNumber = 0;}
virtual void * isInSquare(byte identity);
void put(int x, int y);
void remove(void);
void fineMoveRel(int x, int y);
void moveTo(int x, int y);
int hit(animactor * target);
virtual void advance();
virtual void show(int x, int y, word pagebase);
virtual void draw(int x, int y, word pagebase);
virtual void spawn(animactor * spawnactor);
virtual void assignIcon(byte iconNumber, byte identity = 255);
virtual void turn(byte idirection) {};
static void loadActor(int position, char far * filename, yakLib * myYakLib = NULL);
};
#endif
class animactor : public animslave, public script
{
public:
byte myIconNumber; // what do we look like?
byte myIdentity; // ...and what ARE we?
analagous to the similar numbers in the animap class
word mapX, mapY; //position on parent map
byte squareX, squareY; //position on map square, so we can move finely
squarex and squarey are pixel placements. This lets us get away with the
illusion that we're not really on a grid!
animactor * nextActor;
points to the next actor on the square. Actors are inserted into the list
in z-order so that they "stack" correctly (ie actor "A", behind actor "B",
doesn't overwrite it)
animactor * spawningActor;
animactor * spawnedActor;
A little more confusing, spawning allows you to temporarily reassign an actor
to a different graphic. Useful for changing actions of an actor (a regular
actor might be a tank rolling along, which could "spawn" into a firing tank
during combat, for example.) Particularly useful with events.
animap * mymap;
pointer to the map the actor is on.
static animicon * actorIcons;
A table of animicons the actors use to slave off of. Filled using loadActor
animactor() : animslave() {nextActor = spawnedActor = spawningActor = NULL; mymap = NULL; mapX = mapY = squareX = squareY = myIconNumber = 0;}
default constructor
virtual void * isInSquare(byte identity);
checks to see if there is an actor with identity (identity) in the same square
as this actor. Very useful!
void put(int x, int y);
Puts actor on the map. Be careful you don't put more than one copy!
void remove(void);
Pulls actor off the map.
void fineMoveRel(int x, int y);
Moves actor (x, y) pixels, updating mapx, mapy, squarex, squarey as appropriate
void moveTo(int x, int y);
Moves actor to map square (x, y).
int hit(animactor * target);
Looks to see if this actor hit the target actor.
virtual void advance();
advances actor one frame of animation and one line of script.
virtual void show(int x, int y, word pagebase);
Shows actor and updates a frame/script line.
virtual void draw(int x, int y, word pagebase);
draws actor; does not advance.
virtual void spawn(animactor * spawnactor);
changes graphic to that of the spawnactor.
virtual void assignIcon(byte iconNumber, byte identity = 255);
Assigns icon to an entry in the icon table.
virtual void turn(byte idirection) {};
Put here to make factor.cpp work right. Does nothing to actors.
static void loadActor(int position, char far * filename, yakLib * myYakLib = NULL);
loads an icon into the position (position) in the actorIcons table.
};
Associated with Actors are Events, neat little pseudo-actors with a special
property. Ordinarily, when something like an explosion happens, the user
must keep track of where it is, what frame it's on, etc, putting it on the
map and taking it off when done. Events are "fire-and-forget" animations
that allocate their own living space, run their animation, and deallocate their
space when the animation is complete. Use for explosions, spell effects,
missiles, whatever!
--------------------------------------------------------------------------
THE EVENT CLASS
#ifndef EVENT.H
#define EVENT.H
#include "actor.h"
#define MAX_EVENTS 10
class event : public animactor
{
public:
void advance(void);
void addAt(int x, int y, int sqx, int sqy);
static animicon * eventIcons;
void assignEvent(byte icon_number, byte identity = 255);
static void loadEvent(int position, char far * filename, yakLib * myYakLib = NULL);
};
#endif
{
void advance(void);
Advances a frame of animation and a line of script. If the end of the animation
has been reached, removes the event and cleans up after itself. If the event
was spawned (belongs to another actor), the event returns control to the
parent actor when animation is over.
void addAt(int x, int y, int sqx, int sqy);
adds a new copy of the event at the coordinates given to the event's *myMap.
static animicon * eventIcons;
like actorIcons
void assignEvent(byte icon_number, byte identity = 255);
like assignActor
static void loadEvent(int position, char far * filename, yakLib * myYakLib = NULL);
like loadActor
}
Of course, actors that stay in the same position--even if moving-- aren't
interesting. If something is traveling left, it should face left; a facing-
actor class is needed. I have just the thing: the factor (facing-actor) class!
-------------------------------------------------------------------------
THE FACTOR CLASS
#ifndef FACTOR.H
#define FACTOR.H
#include "actor.h"
#define MAX_FACTORS 10
typedef animicon directionTable[10];
class factor : public animactor //facing-actor
{
public:
enum direction {special, southwest, south, southeast, west, center, east,
northwest, north, northeast};
enum type {eightFace, twoFace, oneFace, fourFace};
animiconNode * directionIcons[10];
byte direction;
factor() {direction = 5;};
virtual void advance();
void turn(byte idirection);
virtual void spawn(animactor * spawnactor);
void assignIcon(int icon_number, type mode, char identity = 255);
static directionTable * ficonTable;
static void loadFactor(int position, char * special, char * sw, char * s,
char * se, char * w, char * center, char * e,
char * nw, char * n, char * ne, yakLib * myYakLib = NULL,
icon::flagType flags = icon::normal);
static void clearFactor(int position);
};
#endif
{
public:
enum direction {special, southwest, south, southeast, west, center, east,
northwest, north, northeast};
The enumerated type containing numbers for all the directions. These cor-
respond to the numbers on your numeric keypad, with zero being "special".
enum type {eightFace, twoFace, oneFace, fourFace};
This is the enumerated type declaring how the icon will be drawn:
eightFace: different facing for all directions
twoFace : all west-facing directions and one n-s direction are the same
icon; all east-facing directions and the other n-s are also
one icon
fourFace : all diagonal directions show the icon for that e-w direction.
oneFace : why use this? It's just like an actor!
animiconNode * directionIcons[10];
The table of icon nodes used for the different directions. Each points to
a different animicon.
byte direction;
Current direction of the factor
factor() {direction = 5;};
default constructor. This probably should be a little more robust.
virtual void advance();
like actor::advance.
void turn(byte idirection);
turns the character to the specified direction. This should probably require
an enumerated direction type.
virtual void spawn(animactor * spawnactor);
like actor::spawn. Notice that this takes an animactor pointer as an argument,
so factors can spawn actors and vice versa. Remember the turn() stub function
back in actor.h? This is why.
void assignIcon(int icon_number, int mode, char identity = 255);
Like assignActor, etc. This points the whole table to an entry in the ficontable
static directionTable * ficonTable;
Directiontable is an array of animicons; ficonTable is an array of these!
static void loadFactor(int position, char * special, char * sw, char * s,
char * se, char * w, char * center, char * e,
char * nw, char * n, char * ne, yakLib * myYakLib = NULL,
icon::flagType flags = icon::normal);
Looks complex, but this really is just a factor'ed version of the loadActor,
etc functions. Give it a filename for each of the directions, and it loads in
all frames of the animation in question.
static void clearFactor(int position);
frees up memory occupied by the icons in ficonTable[position].
};
And of course, to keep things round, the fevent class, for facing-missiles
or what have you.
--------------------------------------------------------------------------
THE FEVENT CLASS
#ifndef FEVENT.H
#define FEVENT.H
#include "factor.h"
#define MAX_FEVENTS 10
class fevent : public factor
{
public:
void advance(void);
void addAt(int x, int y, int sqx, int sqy);
void assignFevent(int icon_number, int mode, byte identity = 255);
static directionTable * feventTable;
static void loadFevent(int position, char * special, char * sw, char * s,
char * se, char * w, char * center, char * e,
char * nw, char * n, char * ne, yakLib * myYakLib = NULL,
icon::flagType flags = icon::normal);
};
#endif
{
public:
void advance(void);
See event::advance
void addAt(int x, int y, int sqx, int sqy);
see event
void assignFevent(int icon_number, int mode, byte identity = 255);
see assignFactor
static directionTable * fevent_table;
see factorTable.
static void loadFevent(int position, char * special, char * sw, char * s,
char * se, char * w, char * center, char * e,
char * nw, char * n, char * ne, yakLib * myYakLib = NULL,
icon::flagType flags = icon::normal);
see loadFactor
};
Okay! This is the basic class infrastructure for yakIcons. The rest of
the modules are just icing on the cake, but what icing! Documentation for
the support modules of yakIcons is in yicons2.doc.